<?php

/**
 * Description of Acl
 *
 * @author marcio
 */
abstract class ZFPainel_Acl
{

    /**
     *
     * @var Zend_Acl
     */
    protected $aclInstance;
    protected $forbidden = false;
    protected $forbiddenMsg;
    protected $recursos = array();
    protected $herancaRecursos = array();
    protected $recursosRoleAdminDeny = array();
    protected $recursosRoleAllAllowed = array();
    protected $resources = array();
    protected $restricoes = array();

    /**
     * Retorna uma lista com os papeis do usuario
     */
    abstract protected function getUserRoles($cdAdmin);

    /**
     * Retorna uma lista dos privilegios dos papeis fornecidos
     */
    abstract protected function getRolesPrivilegies($papeis);

    /**
     * Retorna uma lista de todos os papeis
     */
    abstract protected function getRoles();

    /**
     * Verifica se o usuario logado possui o $actionTestar liberado
     * 
     * @param int $actionTestar
     * @param array $params
     * @return boolean
     * @throws ZFPainel_Exception_Resource_NotFound
     * @throws ZFPainel_Exception_Auth_Unauthorized
     */
    public function checkPermission($actionTestar, array $params = null)
    {
        if (null != $actionTestar) {
            $identity = ZFPainel_Auth::getInstance()->getIdentity();
            $papeis = $this->getUserRoles($identity->cdAdmin);
            
            // Recursos para o papel
            $recursosPapel = $this->getRolesPrivilegies($papeis);
            
            $actions = $this->resources->getResources();
            
            if (!isset($actions[$actionTestar])) {
                throw new ZFPainel_Exception_Resource_NotFound("Recurso {$actionTestar} não encontrado no array resources.");
            }

            foreach ($actions as $action => $actionConfigs) {
                foreach ($actionConfigs as $actionConfig) {
                    if ($action === $actionTestar) {
                        
                        $avancarOK = true;

                        if (isset($actionConfig['recursos'])) {
                            foreach ($actionConfig['recursos'] as $recurso) {
                                if (!$this->checkRecursoPapelLiberado($recurso)) {
                                    $avancarOK = false;
                                    break;
                                }
                            }
                        }

                        if (!$avancarOK) {
                            continue;
                        }

                        // Testa se o recurso tem alguma restricao
                        if (isset($actionConfig['params'])) {
                            foreach ($actionConfig['params'] as $key => $value) {
                                if ((!isset($params[$key])) || ($params[$key] != $value)) {
                                    $avancarOK = false;
                                    break;
                                }
                            }
                        }

                        if ($avancarOK) {
                            return true;
                        }
                    }
                }
            }
        }

        throw new ZFPainel_Exception_Auth_Unauthorized("Acesso negado");
    }
    
    /**
     * Checa se o recurso esta liberado para um dos papeis do usuario
     * 
     * @param type $recurso
     * @return boolean
     */
    public function checkRecursoPapelLiberado($recurso)
    {
        $identity = ZFPainel_Auth::getInstance()->getIdentity();
        $papeis = $this->getUserRoles($identity->cdAdmin);
        $recursosPapel = $this->getRolesPrivilegies($papeis);

        if (in_array($recurso, $recursosPapel)) {
            return true;
        }
        return false;
    }

    public function checkPermission_antigo($action = null, array $param = null)
    {
        if (null != $action) {
            $identity = ZFPainel_Auth::getInstance()->getIdentity();
            $papeis = $this->getUserRoles($identity->cdAdmin);
            $recursosLiberados = $this->getRolesPrivilegies($papeis);

            for ($i = 0, $iMax = count($recursosLiberados); $i < $iMax; $i++) {
                $recurso = $this->resources->getResource($recursosLiberados[$i]);
                if (isset($recurso)) {
                    if (in_array($action, $recurso)) {
                        if (isset($this->restricoes[$action])) {
                            foreach ($this->restricoes[$action] as $restricaoRecurso => $restricaoParam) {
                                foreach ($restricaoParam as $k => $v) {
                                    if (isset($param[$k])) {
                                        if ($param[$k] == $v) {
                                            if (in_array($restricaoRecurso, $recursosLiberados)) {
                                                return true;
                                            } else {
                                                throw new ZFPainel_Exception_Auth_Unauthorized("Acesso negado");
                                            }
                                        }
                                    } else {
                                        throw new ZFPainel_Exception_Auth_Unauthorized("Parâmetro {$k} necessário não passado no parâmetro da tela.");
                                    }
                                }
                            }
                        } else {
                            return true;
                        }
                    }
                } else {
                    throw new ZFPainel_Exception_Auth_Unauthorized("Recurso {$recursosLiberados[$i]} não encontrado no array resources.");
                }
            }
        }
        throw new ZFPainel_Exception_Auth_Unauthorized("Acesso negado");
    }

}
